package com.suredy.core.ctrl;

import java.rmi.RemoteException;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.remoting.rmi.RmiProxyFactoryBean;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;

import com.suredy.Constants;
import com.suredy.PropertiesLoader;
import com.suredy.base.model.User;
import com.suredy.core.model.BaseFlowModel;
import com.suredy.core.service.BaseSrv;

import eabnp.basic.result.IResult;
import eabnp.eflow.client.impl.local.IEFlowClientRmi;
import eabnp.eflow.info.ctrlinfo.processctrl.ProcessCtrl;
import eabnp.eflow.session.ESession;

public class BaseCtrl {

	private final static Logger log = LoggerFactory.getLogger(BaseCtrl.class);

	@Autowired
	@Qualifier("com.suredy.core.service.BaseSrv")
	private BaseSrv baseSrv;

	protected final String CODE_ERR_MSG = "err_msg";

	protected String getContextPath() {
		return this.getRequest().getContextPath();
	}

	protected HttpServletRequest getRequest() {
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
	}

	protected HttpSession getSession() {
		return this.getRequest().getSession();
	}

	protected void setSessionAttribute(String name, Object value) {
		if (StringUtils.isBlank(name))
			throw new IllegalArgumentException("Invalid parameter String[key].");

		this.getSession().setAttribute(name, value);
	}

	protected Object getSessionAttribute(String name) {
		if (StringUtils.isBlank(name))
			throw new IllegalArgumentException("Invalid parameter String[key].");

		return this.getSession().getAttribute(name);
	}

	protected void removeSessionAttribute(String name) {
		if (StringUtils.isBlank(name))
			throw new IllegalArgumentException("Invalid parameter String[key].");

		this.getSession().removeAttribute(name);
	}

	protected Object getAndRemoveSessionAttribute(String name) {
		if (StringUtils.isBlank(name))
			throw new IllegalArgumentException("Invalid parameter String[key].");

		Object val = this.getSessionAttribute(name);

		this.removeSessionAttribute(name);

		return val;
	}

	protected User getUser() {
		Object val = this.getSessionAttribute(Constants.LOGIN_USER);

		if ((val == null) || (!User.class.isInstance(val))) {
			return null;
		}
		return (User) val;
	}

	protected void setUser(User user) {
		this.setSessionAttribute(Constants.LOGIN_USER, user);
	}

	protected void clearSession() {
		HttpSession session = this.getSession();

		session.invalidate();
	}

	protected void setESession(ESession es) {
		HttpSession session = getRequest().getSession();
		session.setAttribute(Constants.FLOW_SESSION, es);
	}

	protected ESession getESession() {
		HttpSession session = getRequest().getSession();
		Object val = session.getAttribute(Constants.FLOW_SESSION);
		return (ESession) val;
	}

	protected IEFlowClientRmi getEFlowClient() {
		IEFlowClientRmi client = null;
		try {
			RmiProxyFactoryBean factory = new RmiProxyFactoryBean();
			factory.setServiceInterface(IEFlowClientRmi.class);
			factory.setServiceUrl(PropertiesLoader.getString(Constants.FLOW_RMI));
			factory.setCacheStub(false);
			factory.setLookupStubOnStartup(true);
			factory.afterPropertiesSet();
			client = (IEFlowClientRmi) factory.getObject();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return client;
	}

	protected String launchFlow(String flowCode) {
		String sessionId = getESession().getSessionId();
		try {
			IResult result = getEFlowClient().Exec("launchProcess", new Object[] {sessionId, flowCode});
			if (result.isSuccess())
				return ((ProcessCtrl) result.getResultObject()).getProcessId();
		} catch (RemoteException e) {
			e.printStackTrace();
		}

		return null;
	}

	protected void addBlankTodo(String flowUN, String nodeName, String title, String id, String url, String processId) {
		String sessionId = getESession().getSessionId();
		try {
			int i = 0;
			getEFlowClient().Exec("addTodo", new Object[] {sessionId, processId, getUser().getUserNo(), getUser().getShortName(), getUser().getUserNo(), getUser().getShortName(), flowUN, title, nodeName, url, id, Integer.valueOf(i)});
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}

	protected String createTodoUri(String formUri, String fileId) {
		if (StringUtils.isBlank(formUri) || StringUtils.isBlank(fileId))
			throw new IllegalArgumentException("Invalid parameters. Please check it now.");

		if (formUri.indexOf("{id}") == -1)
			throw new IllegalArgumentException("Invalid parameter String[formUri]. It must contain a placeholder '{id}'.");

		String cp = this.getContextPath();

		if (!StringUtils.isBlank(cp) && formUri.startsWith(cp))
			cp = "";

		if (!formUri.startsWith("/"))
			cp += "/";

		formUri = cp + formUri;

		return formUri.replace("{id}", fileId);
	}

	protected <T extends BaseFlowModel> T createFlow(T t, String fileTypeCode, String flowCode, String formUri) {
		if (t == null || StringUtils.isBlank(fileTypeCode) || StringUtils.isBlank(flowCode) || StringUtils.isBlank(formUri))
			throw new IllegalArgumentException("Invalid parameters. Please check it now.");

		if (this.getUser() == null)
			throw new RuntimeException("Can not get login user info.");

		String processId = this.launchFlow(flowCode);

		if (StringUtils.isBlank(processId)) {
			log.error("Can not create a new flow with code[" + flowCode + "].");
			return null;
		}

		t.setProcessId(processId);
		t.setFileTypeCode(fileTypeCode);
		t.setCreateTime(new Date());
		t.setCreatorCode(this.getUser().getUserCode());
		t.setCreatorFullName(this.getUser().getFullName());
		t.setCreatorUnitCode(this.getUser().getUnitCode());

		t = this.baseSrv.saveOrUpdate(t);

		if (t == null)
			throw new RuntimeException("Save business flow entity error.");

		this.addBlankTodo(flowCode, "草稿", "[空白文件]", t.getId(), this.createTodoUri(formUri, t.getId()), processId);

		return t;
	}
	
	public boolean updateTodo(BaseFlowModel t,String title,String url){
		String sessionId = getESession().getSessionId();
		String processId = t.getProcessId();
		try {
			getEFlowClient().Exec("resetTodoInfo", new Object[] {sessionId, processId,title,url,t.getId()});
		} catch (RemoteException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * Redirect to error page
	 * 
	 * @param errMsg
	 * @return
	 */
	protected ModelAndView gotoErrorPage(String errMsg) {
		ModelAndView view = new ModelAndView("error");

		view.addObject("msg", errMsg);

		return view;
	}
}
